﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using DataSimDLL;
using System.ComponentModel;
using System.IO;
using System.Threading;
using Microsoft.Win32;

namespace BDSim
{
    /// <summary>
    /// LoadSp3DataWnd.xaml 的交互逻辑
    /// </summary>
    public partial class LoadSp3DataWnd : Window, INotifyPropertyChanged
    {
        public LoadSp3DataWnd()
        {
            InitializeComponent();
        }
        #region //事件

        //属性改变通知时间
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        private ObservableCollection<SP3OneEpoch> _SP3DataInfo = new ObservableCollection<SP3OneEpoch>();

        public ObservableCollection<SP3OneEpoch> SP3DataInfo
        {
            get { return _SP3DataInfo; }
            set { _SP3DataInfo = value; NotifyPropertyChanged("SP3DataInfo"); }
        }
        private string _State = "未读取";

        public string State
        {
            get { return _State; }
            set { _State = value; NotifyPropertyChanged("State"); }
        }
       // private int _Progress = 0;

        //public int Progress
        //{
        //    get { return _Progress; }
        //    set { _Progress = value; NotifyPropertyChanged("Progress"); }
        //}
        private int _SelectIndex = -1;

        public int SelectIndex
        {
            get { return _SelectIndex; }
            set
            {
                _SelectIndex = value;
                NotifyPropertyChanged("SelectIndex");

                if (value >= 0)
                {
                    IsEnable = true;
                }
                else
                {
                    IsEnable = false;
                }

                selectSP3Data.Clear();
                foreach (var item in data[SelectIndex].Rec)
                {
                    if (item.PRN != 0)
                    {
                        SelectSat temp = new SelectSat();
                        temp.IsChecked = true;
                        temp.PRN = item.PRN;
                        temp.Name = head.SysType + (item.PRN.ToString()).PadLeft(2, '0');
                        selectSP3Data.Add(temp);
                    }
                }
            }
        }

        /// <summary>
        /// 界面选择卫星编号
        /// </summary>
        private ObservableCollection<SelectSat> selectSP3Data = new ObservableCollection<SelectSat>();

        public ObservableCollection<SelectSat> SelectSP3Data
        {
            get { return selectSP3Data; }
            set { selectSP3Data = value; NotifyPropertyChanged("SelectSP3Data"); }
        }


        private bool _IsEnable = false;
        /// <summary>
        /// 使能端口，绑定到导入卫星按钮，控制按钮是否可用状态
        /// </summary>
        public bool IsEnable
        {
            get { return _IsEnable; }
            set { _IsEnable = value; NotifyPropertyChanged("IsEnable"); }
        }
        /// 

        public string FilePath = "";

        int InterN = 11;
        public RinexFileDataType.SP3Head head = new RinexFileDataType.SP3Head();
        public List<RinexFileDataType.SP3Data> data = new List<RinexFileDataType.SP3Data>();
        public NodePosVelClass[] SatInitPV_ECF;
        public NodePosVelClass[] SatInitPV_ECI;
        public int [] Prn;
        public char GnssFlag;
        public int SatNum;
        public UTCTime SelectEpoch = new UTCTime();

        unsafe private void Load_Click(object sender, RoutedEventArgs e)
        {
            int Total = data.Count;
            SatNum = head.SatCount;
            Prn = new int[SatNum];
            SatInitPV_ECF = new NodePosVelClass[SatNum];
            SatInitPV_ECI = new NodePosVelClass[SatNum];
            double[, ,] PosList = new double[InterN, SatNum, 3];//【历元，卫星数，3维坐标】
            double[] PT = new double[InterN];
            int left = 0;
            int right = 0;
            if (SelectIndex <= 5)
            {
                left = 0;
                right = InterN;
            }
            else if (SelectIndex < Total - 5 && SelectIndex>5)
            {
                left = SelectIndex - 5;
                right = SelectIndex + 5 + 1;
            }
            else
            {
                left = Total - InterN;
                right = Total;
            }
            int index = 0;
            for (int i = left; i < right; i++)
            {
                for (int j = 0; j < SatNum; j++)
                {
                    PosList[index, j, 0] = data[i].Rec[j].x * 1000;
                    PosList[index, j, 1] = data[i].Rec[j].y * 1000;
                    PosList[index, j, 2] = data[i].Rec[j].z * 1000;
                }
                PT[index] = i * head.SampPeriod;
                index++;
            }

            //插值求卫星的速度           
            NodePosVel[] SatPV_ECF = new NodePosVel[SatNum];
            NodePosVel[] SatPV_ECI = new NodePosVel[SatNum];
            double[] PosX = new double[InterN];
            double[] PosY = new double[InterN];
            double[] PosZ = new double[InterN];
            for (int i = 0; i < SatNum; i++)
            {
                //X
                for (int j = 0; j < InterN; j++)
                {
                    PosX[j] = PosList[j, i, 0];
                }
                SatPV_ECF[i].X = data[SelectIndex].Rec[i].x * 1000;
                CInterpolateDLL.DLagrange(SelectIndex * head.SampPeriod, InterN, PT, PosX, ref SatPV_ECF[i].vx);
                //Y
                for (int j = 0; j < InterN; j++)
                {
                    PosY[j] = PosList[j, i, 1];
                }
                SatPV_ECF[i].Y = data[SelectIndex].Rec[i].y * 1000;
                CInterpolateDLL.DLagrange(SelectIndex * head.SampPeriod, InterN, PT, PosY, ref SatPV_ECF[i].vy);
                //Z
                for (int j = 0; j < InterN; j++)
                {
                    PosZ[j] = PosList[j, i, 2];
                }
                SatPV_ECF[i].Z = data[SelectIndex].Rec[i].z * 1000;
                CInterpolateDLL.DLagrange(SelectIndex * head.SampPeriod, InterN, PT, PosZ, ref SatPV_ECF[i].vz);
            }

            ///根据选择的历元重新读取极移文件
            SelectEpoch = data[SelectIndex].Epoch;
            TimeSpaceDll.CAL2UTC(out SelectEpoch, 1);

            UTCTime EopStart =SelectEpoch;
            EopStart.JD = EopStart.JD - 1;
            TimeSpaceDll.CAL2UTC(out EopStart, 2);
            UTCTime EopEnd = SelectEpoch;
            EopEnd.JD = EopEnd.JD + 1;
            TimeSpaceDll.CAL2UTC(out EopEnd, 2);
            string FileName = Directory.GetCurrentDirectory() + "\\ConfigFiles\\EOP_BDSim.txt";
            bool ret = BDSim.ReadEOP.EOP_Init(FileName.ToCharArray(), EopStart, EopEnd);
            if (ret == true)
            {
                int count = 0;
                EOPData* pdata = BDSim.ReadEOP.EOP_GetEopData(out count);
                //时空类动态库初始化
                BDSim.TimeSpaceDll.TimeSpaceInit(pdata, count);
            }
            else
            {
                MessageBox.Show("读极移跳秒文件失败！", "错误");
            }

            ///把导航时转成UTC
            if (head.SysType == 'G')
            {
                TimeSpaceDll.GPST2UTC(SelectEpoch.JD, out SelectEpoch.JD);
            }
            if (head.SysType == 'C')
            {
                TimeSpaceDll.BDT2UTC(SelectEpoch.JD, out SelectEpoch.JD);
            }
            TimeSpaceDll.CAL2UTC(out SelectEpoch, 2);

            ///根据界面选择添加卫星
            int satindex = 0;
            int temp = 0;
            foreach (var item in selectSP3Data)
            {
                if (item.IsChecked == true)
                {
                    Prn[satindex] = item.PRN;
                    SatPV_ECF[temp].Epoch = SelectEpoch;
                    TimeSpaceDll.ECF2ECI(SatPV_ECF[temp], 0, 0, out SatPV_ECI[satindex]);
                    NodePosVelClass ecf_Class = new NodePosVelClass();
                    NodePosVelClass eci_Class = new NodePosVelClass();
                    ecf_Class = SatPV_ECF[temp].ConvertToClass();
                    eci_Class = SatPV_ECI[satindex].ConvertToClass();
                    SatInitPV_ECF[satindex] = ecf_Class;
                    SatInitPV_ECI[satindex] = eci_Class;
                    satindex++;
                }
                temp++;
            }

            this.DialogResult = true;
        }

        private void open_Click(object sender, RoutedEventArgs e)
        {
            string currentDirectory = Directory.GetCurrentDirectory();
            OpenFileDialog OpenFile = new OpenFileDialog();
            OpenFile.Title = "选择SP3数据文件";
            OpenFile.InitialDirectory = Directory.GetCurrentDirectory();
            OpenFile.Filter = "SP3|*.sp3";
            if (OpenFile.ShowDialog() == true)
            {
                FilePath = OpenFile.FileName;
                this.Sp3File.Text = FilePath;
                State = "正在读取";
                ReadSp3File();
                State = "读取完毕";
            }
            //  还原路径
            Directory.SetCurrentDirectory(currentDirectory);          
        }
        //delegate void ReadFileDelegate();
        void ReadSp3File()
        {
            RinexFileDLL.SP3Open(FilePath.ToCharArray());
            RinexFileDLL.SP3ReadHeader(1, out head);
            GnssFlag = head.SysType;
            int flag = 0;
            for (int i = 0; i < head.TotalEpoh; i++)
            {
                RinexFileDataType.SP3Data temp = new RinexFileDataType.SP3Data();
                flag = RinexFileDLL.SP3ReadRecoder(1, ref head, out temp);

                data.Add(temp);
                SP3OneEpoch one = new SP3OneEpoch();
                one.ID = i + 1;
                one.Epoch.Year = temp.Epoch.Year;
                one.Epoch.Mon = temp.Epoch.Mon;
                one.Epoch.Day = temp.Epoch.Day;
                one.Epoch.Hour = temp.Epoch.Hour;
                one.Epoch.Min = temp.Epoch.Min;
                one.Epoch.Sec = temp.Epoch.Sec;
                one.SatNum = head.SatCount;
                SP3DataInfo.Add(one);
               // Progress = (i + 1) / head.TotalEpoh * 100;
            }
            RinexFileDLL.SP3Close(1);
        }

        private void Cancel_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }
    }
    public class SP3OneEpoch : INotifyPropertyChanged
    {
        private int _ID;

        public int ID
        {
            get { return _ID; }
            set { _ID = value; NotifyPropertyChanged("ID"); }
        }
        private UTCTimeClass _Epoch=new UTCTimeClass();
        public UTCTimeClass Epoch
        {
            get { return _Epoch; }
            set { _Epoch = value; NotifyPropertyChanged("Epoch"); }
        }

        private int _SatNum=0;
        public int SatNum
        {
          get { return _SatNum; }
          set { _SatNum = value; NotifyPropertyChanged("SatNum"); }
        }

        #region //事件

        //属性改变通知时间
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }


    public class SelectSat : INotifyPropertyChanged
    {
        private bool _IsChecked;

        public bool IsChecked
        {
            get { return _IsChecked; }
            set { _IsChecked = value; NotifyPropertyChanged("IsChecked"); }
        }

        private int _PRN;

        public int PRN
        {
            get { return _PRN; }
            set { _PRN = value; NotifyPropertyChanged("PRN"); }
        }

        private string _Name;

        public string Name
        {
            get { return _Name; }
            set { _Name = value; NotifyPropertyChanged("Name"); }
        }

        

        #region //事件

        //属性改变通知时间
        public event PropertyChangedEventHandler PropertyChanged;

        public void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}
